<template>
  <div class="pro-global-tabs" role="tablist">
    <TabsContainer ref="scrollPanel" @scroll="handleScroll">
      <router-link
        v-for="tag in Array.from(visitedViews)"
        ref="tag"
        :key="tag.path"
        :class="{'is-active': isActive(tag), 'is-sticky': tag.meta.affix}"
        :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
        :aria-selected="isActive(tag) ? 'true' : 'false'"
        :title="tag.title"
        tag="span"
        class="pro-global-tabs-item"
        role="tab"
        active-class
        exact-active-class
        exact
        tabindex="-1"
        @click.middle.native="closeSelectedTag(tag)"
        @contextmenu.prevent.native="openMenu(tag,$event)"
      >
        <span class="label">{{ tag.title }}</span>
        <span v-if="!tag.meta.affix" class="close" title="关闭标签页" @click.prevent.stop="closeSelectedTag(tag)">
          <svg width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
            <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" />
          </svg>
        </span>
      </router-link>
    </TabsContainer>
    <ul ref="menu" v-show="visible" :style="{ left: left + 'px', top: top+'px' }" class="pro-global-tabs-contextmenu">
      <li @click="refreshSelectedTag(selectedTag)">刷新</li>
      <li v-if="!(selectedTag.meta && selectedTag.meta.affix)" @click="closeSelectedTag(selectedTag)">关闭</li>
      <li @click="closeOthersTags">关闭其他</li>
      <li @click="closeAllTags">关闭所有</li>
    </ul>
  </div>
</template>

<script>
import { TabsContainer } from './Container.jsx'
import path from 'path'

export default {
  components: { TabsContainer },
  data() {
    return {
      visible: false,
      top: 0,
      left: 0,
      selectedTag: {},
      affixTags: []
    }
  },
  computed: {
    visitedViews: {
      get() {
        return this.$store.state.tagsView.visitedViews
      },
      set(v) {
        this.$store.dispatch('tagsView/updateVisitedView', v)
      }
    },
    routes() {
      return this.$store.state.permission.routes
    }
  },
  watch: {
    $route() {
      this.addTags()
      this.moveToCurrentTag()
    },
    visible(value) {
      if (value) {
        document.body.addEventListener('click', this.closeMenu)
      } else {
        document.body.removeEventListener('click', this.closeMenu)
      }
    }
  },
  mounted() {
    this.initTags()
    this.addTags()
  },
  methods: {
    isActive(route) {
      return route.path === this.$route.path
    },
    filterAffixTags(routes, basePath = '/') {
      let tags = []
      routes.forEach(route => {
        if (route.meta && route.meta.affix) {
          const tagPath = path.resolve(basePath, route.path)
          tags.push({
            fullPath: tagPath,
            path: tagPath,
            name: route.name,
            meta: { ...route.meta }
          })
        }
        if (route.children) {
          const tempTags = this.filterAffixTags(route.children, route.path)
          if (tempTags.length >= 1) {
            tags = [...tags, ...tempTags]
          }
        }
      })
      return tags
    },
    initTags() {
      const affixTags = this.affixTags = this.filterAffixTags(this.routes)
      for (const tag of affixTags) {
        // Must have tag name
        if (tag.name) {
          this.$store.dispatch('tagsView/addVisitedView', tag)
        }
      }
    },
    addTags() {
      const { name } = this.$route
      if (name) {
        this.$store.dispatch('tagsView/addView', this.$route)
      }
      return false
    },
    moveToCurrentTag() {
      const tags = this.$refs.tag
      this.$nextTick(() => {
        for (const tag of tags) {
          if (tag.to.path === this.$route.path) {
            this.$refs.scrollPanel.moveToTarget(tag)
            // when query is different then update
            if (tag.to.fullPath !== this.$route.fullPath) {
              this.$store.dispatch('tagsView/updateVisitedView', this.$route)
            }
            break
          }
        }
      })
    },
    refreshSelectedTag(view) {
      this.$store.dispatch('tagsView/delCachedView', view).then(() => {
        const { fullPath } = view
        this.$nextTick(() => {
          this.$router.replace({
            path: '/redirect' + fullPath
          })
        })
      })
    },
    closeSelectedTag(view) {
      this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
        if (this.isActive(view)) {
          this.toLastView(visitedViews, view)
        }
      })
    },
    closeOthersTags() {
      this.$router.push(this.selectedTag)
      this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
        this.moveToCurrentTag()
      })
    },
    closeAllTags(view) {
      this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
        if (this.affixTags.some(tag => tag.path === view.path)) {
          return
        }
        this.toLastView(visitedViews, view)
      })
      // this.$router.push('/')
    },
    toLastView(visitedViews, view) {
      const latestView = visitedViews.slice(-1)[0]
      if (latestView) {
        this.$router.push(latestView)
      } else {
        if (view.name === 'Welcome') {
          this.$router.replace({ path: '/redirect' + view.fullPath })
        } else {
          this.$router.push('/')
        }
      }
    },
    openMenu(tag, { clientX, clientY }) {
      const { left: offsetLeft, width: offsetWidth } = this.$el.getBoundingClientRect()
      const menu = this.$refs.menu

      this.visible = true
      this.selectedTag = tag
      this.$nextTick(() => {
        const menuWidth = menu.getBoundingClientRect().width
        let left = clientX - offsetLeft
        if (left + menuWidth > offsetWidth) {
          left = offsetWidth - menuWidth
        }
        this.left = left
        this.top = clientY - 48
      })
    },
    closeMenu() {
      this.visible = false
    },
    handleScroll() {
      this.closeMenu()
    }
  }
}
</script>

<style lang="less">
@pro-tabs-prefix-cls: ~'pro-global-tabs';
@tabs-close-size: 14px;
@tabs-height: 32px;
@border-base: @border-width-base @border-style-base @border-color-split;

.@{pro-tabs-prefix-cls} {
  flex: 0 0 @tabs-height;
  position: relative;
  z-index: 1;
  height: @tabs-height;
  // border-top: @border-base;
  background-color: @white;
  // box-shadow: 0 1px 2px rgba(0,0,0,.1);
  box-shadow: 0 1px 4px fade(@layout-header-background, 8%);

  .Scrollbar__view {
    display: flex;
    align-items: center;
  }

  &-item {
    position: relative;
    display: flex;
    align-items: center;
    min-width: fit-content;
    height: @tabs-height - 6;
    margin-left: 4px;
    padding-left: 8px;
    padding-right: 4px;
    border: @border-base;
    color: @text-color;
    font-size: 12px;
    background-color: @white;
    white-space: nowrap;
    transition: padding .3s cubic-bezier(.645,.045,.355,1);
    cursor: pointer;

    &:hover {
      color: @text-color;
    }

    &:first-child {
      margin-left: 12px;
    }

    // &:hover,
    // &.active,
    // &.fixed {
    //   padding-right: 6px;
    //   padding-left: 8px;
    // }

    &.is-active {
      color: @white;
      background-color: @primary-color;
      border-color: @primary-color;
    }

    .label {
      max-width: 114px; // 确保标签长度是 152px
      margin-right: 4px;
      .text-elip();
    }

    .close {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 20px;
      height: 20px;
      border-radius: 5px;
      text-align: center;
      // color: @text-color;
      font-size: 16px;

      &:hover {
        background-color: fade(@black, 8%);
      }

      // > span {
      //   width: 16px;
      //   height: 16px;
      //   text-align: center;
      //   line-height: 16px;
      //   font-size: 16px;
      // }
    }
  }

  &-contextmenu {
    position: absolute;
    z-index: 1;
    min-width: 80px;
    margin: 0;
    padding: 4px 0;
    font-size: 12px;
    background-color: @white;
    border-radius: @border-radius-base;
    list-style: none;
    // box-shadow: 0 2px 4px rgba(0,0,0,.12);
    // box-shadow: 0 1px 4px fade(@layout-header-background, 8%);
    box-shadow: 0 6px 16px -8px fade(@black, 8), 0 9px 28px 0 fade(@black, 5), 0 12px 48px 16px fade(@black, 3);

    li {
      padding: 6px 12px;
      line-height: 1;
      cursor: pointer;

      &:hover {
        background-color: @item-hover-bg;
      }
    }
  }
}
</style>
